package org.jing.ext.jdbc.mybatis;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.jing.core.lang.EnumFactory;
import org.jing.core.lang.JingException;
import org.jing.core.lang.itf.JEnum;
import org.jing.ext.ftp.FtpFileType;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Description: <br>
 *
 * @author bks <br>
 * @since 2021-09-22 <br>
 */
public class EnumTypeHandler extends BaseTypeHandler<JEnum> {

    private Class<? extends JEnum> type;

    public EnumTypeHandler(Class<? extends JEnum> type) {
        if (null == type) {
            throw new JingException("invalid type input");
        }
        this.type = type;
    }

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, JEnum jEnum, JdbcType jdbcType) throws SQLException {
        if (null == preparedStatement) {
            return;
        }
        Type[] types = jEnum.getClass().getGenericInterfaces();
        Class<?> outputType = null;
        for (Type t$ : types) {
            if (((ParameterizedType) t$).getRawType() == JEnum.class) {
                outputType = (Class<?>) ((ParameterizedType) t$).getActualTypeArguments()[0];
            }
        }
        if (outputType == String.class) {
            preparedStatement.setString(i, (String) jEnum.output());
        }
        else if (outputType == Boolean.class) {
            preparedStatement.setBoolean(i, (Boolean) jEnum.output());
        }
        else if (outputType == Short.class) {
            preparedStatement.setShort(i, (Short) jEnum.output());
        }
        else if (outputType == Integer.class) {
            preparedStatement.setInt(i, (Integer) jEnum.output());
        }
        else if (outputType == Long.class) {
            preparedStatement.setLong(i, (Long) jEnum.output());
        }
        else if (outputType == Float.class) {
            preparedStatement.setFloat(i, (Float) jEnum.output());
        }
        else if (outputType == Double.class) {
            preparedStatement.setDouble(i, (Double) jEnum.output());
        }
        else if (outputType == BigDecimal.class) {
            preparedStatement.setBigDecimal(i, (BigDecimal) jEnum.output());
        }
        else {
            preparedStatement.setObject(i, jEnum.output());
        }
    }

    @Override public JEnum getNullableResult(ResultSet resultSet, String s) throws SQLException {
        try {
            return EnumFactory.mapEnum(type, resultSet.getObject(s));
        }
        catch (JingException e) {
            throw new SQLException(e);
        }
    }

    @Override public JEnum getNullableResult(ResultSet resultSet, int i) throws SQLException {
        try {
            return EnumFactory.mapEnum(type, resultSet.getObject(i));
        }
        catch (JingException e) {
            throw new SQLException(e);
        }
    }

    @Override public JEnum getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        try {
            return EnumFactory.mapEnum(type, callableStatement.getObject(i));
        }
        catch (JingException e) {
            throw new SQLException(e);
        }
    }

    public static void main(String[] args) throws Exception {
        new EnumTypeHandler(FtpFileType.class).setNonNullParameter(null, 0, FtpFileType.BINARY, null);
    }
}
